package Dm

import (
	"fmt"
	"db2s/ETL"
	"db2s/global"
	"db2s/parDef"
	"db2s/ref"
	"strings"
)

func (pm PartitionMe) Set(parameter string, value any) (err error) {
	return ref.UpdateStructJsonValue(pm, parameter, value)
}
func (pm PartitionMe) Result(object string) global.Return {
	switch object {
	default:
		return global.Return{}
	}
}
func (pm PartitionMe) PartType(parameter parDef.Parameter) (result global.Return, err error) {
	var event = "[PartType]"
	var execSql []string
	for _, v := range []string{"ALL_PART_TABLES", "DBA_PART_TABLES"} {
		execSql = append(execSql, fmt.Sprintf("SELECT "+
			"PARTITIONING_TYPE || ',' || SUBPARTITIONING_TYPE AS \"partitionType\""+
			"FROM "+
			" %v "+
			"WHERE OWNER='%v' "+
			"AND TABLE_NAME='%v'",
			v, parameter.Object.Schema, parameter.Object.Table))
	}
	if result, err = forExecQuerySql(event, parameter, ETL.String, execSql); err != nil {
		err = ref.ErrAddPrintf("PartType", err)
		return
	}
	return
}
func (pm PartitionMe) PartSum(parameter parDef.Parameter) (result global.Return, err error) {
	var event = "[PartSum]"
	var execSql []string
	for _, v := range []string{"all_tab_partitions", "dba_tab_partitions"} {
		execSql = append(execSql, fmt.Sprintf(
			"SELECT "+
				"SUM(DECODE(COMPOSITE,'YES',SUBPARTITION_COUNT,1)) AS \"sum\""+
				" FROM "+
				" %v "+
				"WHERE TABLE_OWNER='%v' "+
				"AND TABLE_NAME = '%v'",
			v, parameter.Object.Schema, parameter.Object.Table))
	}
	if result, err = forExecQuerySql(event, parameter, ETL.String, execSql); err != nil {
		err = ref.ErrAddPrintf("PartSum", err)
		return
	}
	if result.Result, err = stringAnyToInt64(result.Result); err != nil {
		err = ref.ErrAddPrintf("PartSum", err)
		return
	}
	return
}
func (pm PartitionMe) selectFromDual(parameter parDef.Parameter, selectBody string) (result []string, err error) {
	var event = "[selectFromDual]"
	var execSql []string
	var res global.Return
	execSql = append(execSql, fmt.Sprintf("SELECT %v", selectBody))
	if strings.Contains(selectBody, "MAXVALUE") || strings.EqualFold(selectBody, "NULL") {
		result = strings.Split(selectBody, ",")
		return
	}
	if res, err = forExecQuerySql(event, parameter, ETL.String, execSql); err != nil {
		err = ref.ErrAddPrintf("selectFromDual", err)
		return
	}
	if res.Result == nil {
		return
	}
	for k, v := range strings.Split(res.Result.(string), ETL.DataColumnsSplit) {
		var p string
		if strings.TrimSpace(strings.ReplaceAll(strings.Split(selectBody, ",")[k], "'", "")) == strings.TrimSpace(v) {
			p = strings.Split(selectBody, ",")[k]
		} else {
			p = v
		}
		if n := strings.Index(v, "+0800"); n != -1 {
			p = fmt.Sprintf("'%v'", strings.TrimSpace(v[:n]))
		}
		result = append(result, p)
	}
	return
}
func (pm PartitionMe) getPartRule(parameter parDef.Parameter) (result global.Return, err error) {
	var event = "[getPartRule]"
	var execSql []string
	for _, v := range []string{"ALL_TAB_PARTITIONS", "DBA_TAB_PARTITIONS"} {
		execSql = append(execSql, fmt.Sprintf("SELECT "+
			"C.PARTITION_NAME AS \"partName\","+
			"C.SUBPARTITION_COUNT AS \"subSum\","+
			"C.PARTITION_POSITION AS \"seq\","+
			"C.HIGH_VALUE AS \"rules\" \n"+
			"FROM %v C \n"+
			"WHERE C.TABLE_OWNER = '%v' AND C.TABLE_NAME = '%v' order by C.PARTITION_POSITION ",
			v, parameter.Object.Schema, parameter.Object.Table))
	}
	if result, err = forExecQuerySql(event, parameter, ETL.SMap, execSql); err != nil {
		err = ref.ErrAddPrintf("getPartRule", err)
		return
	}
	if result.Result == nil {
		return
	}
	var res []parDef.PartRule
	for _, v := range result.Result.([]map[string]any) {
		vv := mapNullActive(v)
		var rul []string
		if rul, err = pm.selectFromDual(parameter, fmt.Sprintf("%v", vv["rules"])); err != nil {
			err = ref.ErrAddPrintf("getPartRule", err)
			return
		}
		vv["rules"] = strings.Join(rul, ",")
		var rule parDef.PartRule
		if err = ref.MapToStruct(vv, &rule); err != nil {
			err = ref.ErrAddPrintf("getPartRule", err)
			return
		}
		res = append(res, rule)
	}
	result.Result = res
	return
}
func (pm PartitionMe) getSubPartRule(parameter parDef.Parameter) (result global.Return, err error) {
	var event = "[getSubPartColumn]"
	var execSql []string
	for _, v := range []string{"ALL_TAB_SUBPARTITIONS", "DBA_TAB_SUBPARTITIONS"} {
		execSql = append(execSql, fmt.Sprintf("SELECT "+
			"C.PARTITION_NAME AS \"partName\","+
			"C.SUBPARTITION_NAME AS \"subPartName\","+
			"C.SUBPARTITION_POSITION AS \"seq\","+
			"C.HIGH_VALUE AS \"rules\" \n"+
			"FROM %v C \n"+
			"WHERE C.TABLE_OWNER = '%v' AND C.TABLE_NAME = '%v' order by C.SUBPARTITION_POSITION ",
			v, parameter.Object.Schema, parameter.Object.Table))
	}
	if result, err = forExecQuerySql(event, parameter, ETL.SMap, execSql); err != nil {
		err = ref.ErrAddPrintf("getSubPartRule", err)
		return
	}
	if result.Result == nil {
		return
	}
	var res []parDef.PartRule
	for _, v := range result.Result.([]map[string]any) {
		vv := mapNullActive(v)
		if strings.EqualFold(fmt.Sprintf("%v", vv["rules"]), "NULL") {
			vv["rules"] = "''"
		}
		var rule parDef.PartRule
		if err = ref.MapToStruct(vv, &rule); err != nil {
			err = ref.ErrAddPrintf("getSubPartRule", err)
			return
		}
		res = append(res, rule)
	}
	result.Result = res
	return
}

func (pm PartitionMe) getPartMeth(parameter parDef.Parameter) (result global.Return, err error) {
	var event = "[getPartMeth]"
	var execSql []string
	var res parDef.PartMeth
	for _, v := range []string{"ALL_PART_TABLES", "DBA_PART_TABLES"} {
		execSql = append(execSql, fmt.Sprintf("SELECT "+
			"C.PARTITIONING_TYPE AS \"first\","+
			"C.SUBPARTITIONING_TYPE AS \"sub\"  \n"+
			"FROM %v C \n"+
			"WHERE C.OWNER = '%v' AND C.TABLE_NAME = '%v'",
			v, parameter.Object.Schema, parameter.Object.Table))
	}
	if result, err = forExecQuerySql(event, parameter, ETL.Map, execSql); err != nil {
		err = ref.ErrAddPrintf("getPartMeth", err)
		return
	}
	if result.Result == nil {
		result.Result = parDef.PartMeth{First: "NULL", Sub: "NULL"}
		return
	}
	pp := mapNullActive(result.Result.(map[string]any))
	if err = ref.MapToStruct(pp, &res); err != nil {
		err = ref.ErrAddPrintf("getPartMeth", err)
		return
	}
	if strings.EqualFold(fmt.Sprintf("%v", pp["first"]), "NONE") {
		pp["first"] = "NULL"
	}
	if strings.EqualFold(fmt.Sprintf("%v", pp["sub"]), "NONE") {
		pp["sub"] = "NULL"
	}
	result.Result = res
	return
}
func (pm PartitionMe) getFirstPartColumn(parameter parDef.Parameter) (result global.Return, err error) {
	var event = "[GetFirstPartName]"
	var execSql []string

	for _, v := range []string{"ALL_PART_KEY_COLUMNS", "DBA_PART_KEY_COLUMNS"} {
		execSql = append(execSql, fmt.Sprintf("SELECT "+
			"C.COLUMN_NAME AS \"partColumn\" \n"+
			"FROM %v C \n"+
			"WHERE C.OWNER = '%v' AND C.NAME = '%v' order by column_position",
			v, parameter.Object.Schema, parameter.Object.Table))
	}
	if result, err = forExecQuerySql(event, parameter, ETL.StringGarth, execSql); err != nil {
		err = ref.ErrAddPrintf("getFirstPartColumn", err)
		return
	}
	return
}
func (pm PartitionMe) getSubPartColumn(parameter parDef.Parameter) (result global.Return, err error) {
	var event = "[getSubPartColumn]"
	var execSql []string

	for _, v := range []string{"ALL_SUBPART_KEY_COLUMNS"} {
		execSql = append(execSql, fmt.Sprintf("SELECT "+
			"C.COLUMN_NAME AS \"partColumn\" \n"+
			"FROM %v C \n"+
			"WHERE C.OWNER = '%v' AND C.NAME = '%v' order by column_position",
			v, parameter.Object.Schema, parameter.Object.Table))
	}
	if result, err = forExecQuerySql(event, parameter, ETL.StringGarth, execSql); err != nil {
		err = ref.ErrAddPrintf("getSubPartColumn", err)
		return
	}
	return
}

func (pm PartitionMe) newPartMetaBaseInit(parameter parDef.Parameter) (result parDef.PartMetaData, err error) {
	var res global.Return
	if res, err = pm.getPartRule(parameter); err != nil {
		err = ref.ErrAddPrintf("newPartMetaBaseInit", err)
		return
	} else {
		switch res.Result.(type) {
		case []parDef.PartRule:
			result.RuleDesc = res.Result.([]parDef.PartRule)
		}
	}
	if res, err = pm.getPartMeth(parameter); err != nil {
		err = ref.ErrAddPrintf("newPartMetaBaseInit", err)
		return
	} else {
		switch res.Result.(type) {
		case parDef.PartMeth:
			result.Meth = res.Result.(parDef.PartMeth)
		}
	}
	if res, err = pm.getFirstPartColumn(parameter); err != nil {
		err = ref.ErrAddPrintf("newPartMetaBaseInit", err)
		return
	} else {
		switch res.Result.(type) {
		case []string:
			result.PartCol = res.Result.([]string)
		}
	}
	if res, err = pm.getSubPartRule(parameter); err != nil {
		err = ref.ErrAddPrintf("newPartMetaBaseInit", err)
		return
	} else {
		switch res.Result.(type) {
		case []parDef.PartRule:
			result.SubPartDesc = res.Result.([]parDef.PartRule)
		}
	}
	if res, err = pm.getSubPartColumn(parameter); err != nil {
		err = ref.ErrAddPrintf("newPartMetaBaseInit", err)
		return
	} else {
		switch res.Result.(type) {
		case []string:
			result.SubPartCol = res.Result.([]string)
		}
	}
	return
}
func (pm PartitionMe) PartMeta(parameter parDef.Parameter) (result global.Return, err error) {
	var baseResult parDef.PartMetaData
	var partName []string
	if baseResult, err = pm.newPartMetaBaseInit(parameter); err != nil {
		err = ref.ErrAddPrintf("PartMeta", err)
		return
	}
	for _, v := range baseResult.RuleDesc {
		partName = append(partName, v.Name)
	}
	baseResult.PartName = partName
	result.Result = baseResult
	return
}
func (pm PartitionMe) NameToRuleClip(parameter parDef.Parameter) (result global.Return, err error) {
	return
}
